package prolog.terms

final class Var() extends Term {
  private var value: Term = this

  private final def unbound = this.eq(value)

  override def ref: Term =
    if (unbound) this else value.ref

  override final def bind_to(x: Term, trail: Trail) = {
    value = x
    trail.push(this)
    true
  }

  final def unify(other: Term, trail: Trail) = {
    val that = other.ref
    if (this.ref.eq(that)) true
    else
      value.bind_to(that, trail)
  }

  final def undo() = value = this

  override def reaction(agent: Term): Term = {
    val R = agent.action(ref)
    if (!R.isInstanceOf[Var]) {
      R.reaction(agent)
    } else
      R
  }

  override def toString = {
    if (unbound) {
      val h: Long = hashCode
      val n: Long = if (h < 0) 2 * (-h) + 1 else 2 * h
      "_" + n
    } else ref.toString
  }
}